package com.android.model.info;

import android.content.Context;
import android.text.TextUtils;

import com.android.app.constant.UrlConstants;
import com.android.model.db.MovieCollectDao;
import com.android.model.entity.res.AccountInfoResult;
import com.android.model.entity.res.AccountTokenResult;
import com.android.model.entity.res.CreateSessionResult;
import com.android.model.entity.res.CreateTicketResult;
import com.android.model.entity.res.CreateTokenResult;
import com.android.model.entity.res.OrderCompletedResult;
import com.android.model.entity.res.OrderResult;
import com.android.model.entity.res.SetTradePWDVerifyResult;
import com.android.model.entity.res.SymbolListResult;
import com.android.model.entity.res.TradePWDVerifyResult;
import com.android.model.entity.res.UserVerifierResult;
import com.android.model.entity.table.MovieCollect;
import com.android.model.net.HttpObserver;
import com.android.model.net.RetrofitUtil;
import com.android.util.AppNecessaryUtils;
import com.android.util.RequestEntityUtils;
import com.android.util.WindowUtils;
import com.android.BuildConfig;
import com.android.model.db.helper.DaoManager;
import com.android.model.entity.res.LoginResult;
import com.android.model.entity.res.SendCodeResult;
import com.android.model.entity.res.UserInfoResult;
import com.android.model.entity.res.VerifyCodeResult;
import com.android.model.net.LifeCycleEvent;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.reactivex.Observable;
import io.reactivex.subjects.PublishSubject;
import retrofit2.Response;

/**
 * author:  TenFace
 * date:    2017/9/27
 * description:  相关的数据处理/提供层。
 * 包含相关的网络请求、数据库操作
 */

public class UserModel {

    private MovieCollectDao mMovieCollectDao;

    public static UserModel getInstance() {
        return UserModel.SingletonHolder.instance;
    }

    private static class SingletonHolder {
        private static final UserModel instance = new UserModel();
    }

    private UserModel() {
        mMovieCollectDao = DaoManager.getInstance().getDaoSession().getMovieCollectDao();
    }

    /***
     *
     * @param ex55Pin ex55Pin，密码重置和设置交易密码时使用
     * @param phone 手机号（包含国家区号）
     * @param codeType 验证码类型（邮箱或者手机）
     * @param operateType 用户操作类型
     */
    public void sendSmsCode(String ex55Pin,
                            String phone,
                            String codeType,
                            String operateType,
                            HttpObserver<SendCodeResult> observer,
                            PublishSubject<LifeCycleEvent> lifecycleSubject) {
        Map<String, String> map = new HashMap<>();
        map.put("ex55Pin", ex55Pin);
        map.put("phone", phone);
        map.put("codeType", codeType);
        map.put("operateType", operateType);

        Observable observable = RetrofitUtil.getApiService().sendSmsCode(map);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     *
     * @param ex55Pin ex55Pin，密码重置和设置交易密码时使用
     * @param phone 手机号（包含国家区号）
     * @param phoneCode 手机验证码
     * @param codeType 验证码类型（邮箱或者手机）
     * @param operateType 用户操作类型
     */
    public void verifySmsCode(String ex55Pin,
                              String phone,
                              String phoneCode,
                              String codeType,
                              String operateType,
                              HttpObserver<VerifyCodeResult> observer,
                              PublishSubject<LifeCycleEvent> lifecycleSubject) {
        Map<String, String> map = new HashMap<>();
        map.put("ex55Pin", ex55Pin);
        map.put("phone", phone);
        map.put("phoneCode", phoneCode);
        map.put("codeType", codeType);
        map.put("operateType", operateType);

        Observable observable = RetrofitUtil.getApiService().verifyCode(map);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     *
     * @param operateType 用户操作类型
     * @param phone 手机号（包含国家区号）
     * @param password 密码
     * @param inviteCode 邀请码
     * @param token token
     * @param observer 订阅者，传入空的Response
     */
    public void getRegisterStatus(String operateType,
                                  String phone,
                                  String password,
                                  String inviteCode,
                                  String token,
                                  HttpObserver<Response<Void>> observer,
                                  PublishSubject<LifeCycleEvent> lifecycleSubject) {

        Map<String, String> map = new HashMap<>();
//        map.put("operateType", operateType);
        map.put("phone", phone);
        map.put("password", password);
//        map.put("inviteCode", inviteCode);

//        Map<String, String> headers = new HashMap<>();
//        headers.put("token", token);

        Observable observable = RetrofitUtil.getApiService().getRegisterStatus(token, map);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     *
     * @param phone 手机号（包含国家区号）
     * @param password 密码
     * @param codeType 验证码类型（邮箱或者手机）
     */
    public void getLoginStatus(String phone,
                               String password,
                               String codeType,
                               HttpObserver<LoginResult> observer,
                               PublishSubject<LifeCycleEvent> lifecycleSubject) {
        Map<String, String> map = new HashMap<>();
        map.put("phone", phone);
        map.put("password", password);
        map.put("codeType", codeType);

        Observable observable = RetrofitUtil.getApiService().getLoginStatus(map);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     *
     * @param phone 手机号
     */
    public void userVerify(String phone,
                           HttpObserver<UserVerifierResult> observer,
                           PublishSubject<LifeCycleEvent> lifecycleSubject) {
        Map<String, String> map = new HashMap<>();
        map.put("phone", phone);

        Observable observable = RetrofitUtil.getApiService().getUserVerify(map);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     *
     * @param token 重置密码页面校验码校验成功后返回的token，token保存在Header#token
     * @param password 密码
     */
    public void resetAccountPassword(String token,
                                     String password,
                                     HttpObserver<Response<Void>> observer,
                                     PublishSubject<LifeCycleEvent> lifecycleSubject) {
        Map<String, String> map = new HashMap<>();
        map.put("password", password);

        Observable observable = RetrofitUtil.getApiService().resetAccountPassword(token, map);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     *
     * @param token 登录成功返回的token，token保存在Header#token
     */
    public void getUserInfo(String token,
                            HttpObserver<UserInfoResult> observer,
                            PublishSubject<LifeCycleEvent> lifecycleSubject) {
        Observable observable = RetrofitUtil.getApiService().getUserInfo(token);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     *
     * @param token 登录成功后返回的token，token保存在Header#token
     * @param password 登录密码
     * @param emailCode 邮箱验证码
     * @param phoneCode 手机验证码
     * @param googleCode 谷歌验证码
     */
    public void verifySetTradePassword(String token,
                                       String password,
                                       String emailCode,
                                       String phoneCode,
                                       String googleCode,
                                       HttpObserver<SetTradePWDVerifyResult> observer,
                                       PublishSubject<LifeCycleEvent> lifecycleSubject) {
        Map<String, String> map = new HashMap<>();
        map.put("password", password);
        map.put("emailCode", emailCode);
        map.put("phoneCode", phoneCode);
        map.put("googleCode", googleCode);

        Observable observable = RetrofitUtil.getApiService().verifySetTradePassword(token, map);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     *
     * @param token 设置交易密码前校验成功后返回的token，token保存在Header#token
     * @param password 交易密码，6位数字
     * @param operateType 用户操作类型
     */
    public void setTradePassword(String token,
                                 String password,
                                 String operateType,
                                 HttpObserver<Response<Void>> observer,
                                 PublishSubject<LifeCycleEvent> lifecycleSubject) {
        Map<String, String> map = new HashMap<>();
        map.put("password", password);
        map.put("operateType", operateType);

        Observable observable = RetrofitUtil.getApiService().setTradePassword(token, map);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     *交易密码校验，创建sso交易Token
     * @param token 登陆成功后返回的token，token保存在Header#token
     * @param password 交易密码，6位数字
     */
    public void verifyTradePassword(String token,
                                    String password,
                                    HttpObserver<TradePWDVerifyResult> observer,
                                    PublishSubject<LifeCycleEvent> lifecycleSubject) {

        Map<String, String> map = new HashMap<>();
        map.put("password", password);

        Observable observable = RetrofitUtil.getApiService().verifyTradePassword(token, map);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     * 获取股票列表
     */
    public void getSymbolList(HttpObserver<List<SymbolListResult>> observer,
                              PublishSubject<LifeCycleEvent> lifecycleSubject) {

        Observable observable = RetrofitUtil.getApiService().getSymbolList();
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     * 查询账户信息
     * @param token
     */
    public void queryAccountInfo(String token,
                                 HttpObserver<AccountInfoResult> observer,
                                 PublishSubject<LifeCycleEvent> lifecycleSubject) {

        String url = UrlConstants.TRADE_QUERY_ACCOUNT_INFO + token;

        Observable observable = RetrofitUtil.getApiService().queryAccountInfo(url);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     * 创建用户的 Token
     * ip 用户的 ip 信息
     * osType 用户客户端类型
     * osVersion 用户客户端版本号
     * resolution 用户客户端分辨率
     * appVersion 用户客户端 app 的版本号
     * deviceId 客户端 设备 ID
     * @param ssoToken 用户Token
     */
    public void createAccountToken(Context context,
                                   String ssoToken,
                                   HttpObserver<AccountTokenResult> observer,
                                   PublishSubject<LifeCycleEvent> lifecycleSubject) {

        Map<String, String> map = new HashMap<>();
        map.put("ip", getOsEntity(context).ip);
        map.put("osType", getOsEntity(context).osType);
        map.put("osVersion", getOsEntity(context).osVersion);
        map.put("resolution", getOsEntity(context).resolution);
        map.put("appVersion", getOsEntity(context).appVersion);
        map.put("deviceId", getOsEntity(context).deviceId);

        String url = UrlConstants.TRADE_CREATE_ACCOUNT_TOKEN + ssoToken;

        Observable observable = RetrofitUtil.getApiService().createAccountToken(map, url);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    public void createToken(String accountId,
                            String tokenType,
                            String accountToken,
                            HttpObserver<CreateTokenResult> observer,
                            PublishSubject<LifeCycleEvent> lifecycleSubject) {

        Map<String, String> map = new HashMap<>();
        map.put("accountId", accountId);
        map.put("tokenType", tokenType);

        String url = UrlConstants.TRADE_CREATE_TOKEN + accountToken;

        Observable observable = RetrofitUtil.getApiService().createToken(map, url);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     * 创建session
     * @param accountId 账户ID
     * @param ssoTradeToken 用户tradeToken
     * @param accountTradeToken 账户tradeToken
     */
    public void createSession(String accountId,
                              String ssoTradeToken,
                              String accountTradeToken,
                              HttpObserver<CreateSessionResult> observer,
                              PublishSubject<LifeCycleEvent> lifecycleSubject) {

        Map<String, String> map = new HashMap<>();
        map.put("accountId", accountId);
        map.put("extension", ssoTradeToken);

        String url = UrlConstants.TRADE_CREATE_SESSION + accountTradeToken;

        Observable observable = RetrofitUtil.getApiService().createSession(map, url);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    /***
     *
     * @param accountId 账户ID
     * @param session 账户session
     */
    public void createTicket(String accountId,
                             String session,
                             HttpObserver<CreateTicketResult> observer,
                             PublishSubject<LifeCycleEvent> lifecycleSubject) {

        Map<String, String> map = new HashMap<>();
        map.put("accountId", accountId);

        String url = UrlConstants.TRADE_CREATE_TICKET + session;

        Observable observable = RetrofitUtil.getApiService().createTicket(map, url);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    public void createNewOrder(String accountId,
                               String ticket,
                               String token,
                               String symbol,
                               String orderType,
                               String orderSide,
                               BigDecimal quantity,
                               BigDecimal limitPrice,
                               HttpObserver<OrderResult> observer,
                               PublishSubject<LifeCycleEvent> lifecycleSubject) {


        Map<String, Object> orderInfo = new HashMap<>();
        orderInfo.put("symbol", symbol);
        orderInfo.put("orderType", orderType);
        orderInfo.put("orderSide", orderSide);
        orderInfo.put("quantity", quantity);
        orderInfo.put("limitPrice", limitPrice);

        Map<String, Object> map = new HashMap<>();
        map.put("accountId", accountId);
        map.put("ticket", ticket);
        map.put("orderInfo", orderInfo);

        String url = UrlConstants.TRADE_CREATE_NEW_ORDER + token;

        Observable observable = RetrofitUtil.getApiService().createNewOrder(map, url);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    public void cancelOrder(String accountId,
                            String orderId,
                            String session,
                            HttpObserver<OrderResult> observer,
                            PublishSubject<LifeCycleEvent> lifecycleSubject) {

        Map<String, String> map = new HashMap<>();
        map.put("accountId", accountId);
        map.put("orderId", orderId);

        String url = UrlConstants.TRADE_CREATE_ACCOUNT_TOKEN + session;

        Observable observable = RetrofitUtil.getApiService().cancelOrder(map, url);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    public void getListCompletedOrder(String accountId,
                                      int page,
                                      int limit,
                                      String token,
                                      HttpObserver<OrderCompletedResult> observer,
                                      PublishSubject<LifeCycleEvent> lifecycleSubject) {

        Map<String, Object> map = new HashMap<>();
        map.put("accountId", accountId);
        map.put("page", page);
        map.put("limit", limit);

        String url = UrlConstants.TRADE_LIST_COMPLETED_ORDER + token;

        Observable observable = RetrofitUtil.getApiService().getListCompletedOrder(url, map);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }

    public void getListOpenOrder(String accountId,
                                 String token,
                                 HttpObserver<List<OrderResult>> observer,
                                 PublishSubject<LifeCycleEvent> lifecycleSubject) {

        String url = UrlConstants.TRADE_LIST_OPEN_ORDER + token;

        Observable observable = RetrofitUtil.getApiService().getListOpenOrder(url, accountId);
        RetrofitUtil.composeToSubscribe(observable, observer, lifecycleSubject);
    }


    public void deleteFromMyCollect(MovieCollect movieCollect) {
        mMovieCollectDao.delete(movieCollect);
    }


    public int getCollectCount() {
        return (int) mMovieCollectDao.count();
    }


    public List<MovieCollect> getAllCollect() {
        mMovieCollectDao.detachAll();
        return mMovieCollectDao.queryBuilder().list();

    }

    /**
     * 获取手机信息
     *
     * @param context context
     * @return 手机信息
     */
    private RequestEntityUtils.OsEntity getOsEntity(Context context) {
        RequestEntityUtils.OsEntity osEntity = new RequestEntityUtils.OsEntity();
        osEntity.osType = "ANDROID";
        osEntity.osVersion = android.os.Build.VERSION.RELEASE;
        osEntity.resolution = WindowUtils.getScreenWidth(context) + "*" + WindowUtils.getScreenHeight(context);
        osEntity.appVersion = BuildConfig.VERSION_CODE + "";
        String machineImEi = AppNecessaryUtils.getUUId(context);

        if (!TextUtils.isEmpty(machineImEi)) {
            osEntity.deviceId = machineImEi;
        }

        String localIpAddress = AppNecessaryUtils.getLocalIpAddress();
        if (!TextUtils.isEmpty(localIpAddress)) {
            osEntity.ip = localIpAddress;
        }

        return osEntity;
    }

}
